#include "stdafx.h"
#include "GameStateRenderSystem.h"

#include "Components\CameraComponent.h"
#include "Components\GaulemRenderableComponent.h"

#include "Event.h"
#include "EntityEvent.h"

using namespace std;
using namespace ZeEngine;

GameStateRenderSystem::GameStateRenderSystem()
{
	AddRequiredComponent("GaulemRenderableComponent");
}


GameStateRenderSystem::~GameStateRenderSystem()
{
}

bool GameStateRenderSystem::Init(GameEngine& gameEngine)
{
    EntityManager& entityManager = gameEngine.GetEntityManager();

	bool fSuccess = RenderSystem::Init(gameEngine);

    m_screenResolution = gameEngine.GetConfiguration().GetLogicalResolution();

    gameEngine.AddEventListener(this);

SDL_Rect viewport;

viewport.x = 0;
viewport.y = 0;
viewport.w = static_cast<int>(m_screenResolution.GetX());
viewport.h = static_cast<int>(m_screenResolution.GetY() / 4);

m_topViewPort = m_renderer.AddViewport(viewport);

viewport.x = 0;
viewport.y = static_cast<int>(m_screenResolution.GetY() / 4);
viewport.w = static_cast<int>(m_screenResolution.GetX());
viewport.h = static_cast<int>(m_screenResolution.GetY() * .75);

m_bottomViewPort = m_renderer.AddViewport(viewport);

return fSuccess;
}

void GameStateRenderSystem::Destroy(GameEngine& gameEngine)
{
    gameEngine.RemoveEventListener(this);
}

void GameStateRenderSystem::Render(SDL_Renderer& renderer, GameEngine& gameEngine, float interpolation)
{
    EntityManager& entityManager = gameEngine.GetEntityManager();

    RenderTopViewport(renderer, entityManager, interpolation);
    RenderBottomViewport(renderer, entityManager, interpolation);

    RenderImpl(renderer);
}

void GameStateRenderSystem::RenderTopViewport(SDL_Renderer& renderer, EntityManager& entityManager, float interpolation)
{
    if (m_pGaulemCameraComponent)
    {
        EntityDataStore& store = entityManager.GetEntityDataStore("top");

        for each (Entity* pEntity in store)
        {
            if (pEntity && IsEntitySupported(pEntity))
            {
                auto pGaulemRenderableComponent = pEntity->GetComponent<GaulemRenderableComponent>();

                if (pGaulemRenderableComponent && pGaulemRenderableComponent->IsOnTop())
                {
                    RenderEntity(renderer, interpolation, pEntity, m_pGaulemCameraComponent, m_topViewPort);
                }
            }
        }
    }
}

void GameStateRenderSystem::RenderBottomViewport(SDL_Renderer& renderer, EntityManager& entityManager, float interpolation)
{
    if (m_pBaseCameraComponent)
    {
        EntityDataStore& store = entityManager.GetEntityDataStore("bottom");

        for each (Entity* pEntity in store)
        {
            if (pEntity && IsEntitySupported(pEntity))
            {
                auto pGaulemRenderableComponent = pEntity->GetComponent<GaulemRenderableComponent>();

                if (pGaulemRenderableComponent && !pGaulemRenderableComponent->IsOnTop())
                {
                    RenderEntity(renderer, interpolation, pEntity, m_pBaseCameraComponent, m_bottomViewPort);
                }
            }
        }
    }
}

void GameStateRenderSystem::RenderEntity(SDL_Renderer& renderer, float interpolation, Entity* pEntity, CameraComponent* pCameraComponent, u32 viewPortID)
{
    auto pTransformComponent = pEntity->GetComponent<TransformComponent>();
    auto pSpriteComponent = pEntity->GetComponent<SpriteComponent>();
    auto pAnimatedComponent = pEntity->GetComponent<AnimatedComponent>();

    if (pTransformComponent)
    {
        Vector2D<float> position = Vector2D<float>(pTransformComponent->GetPosition().GetX(), pTransformComponent->GetPosition().GetY());

        SDL_Rect b = { static_cast<int>(pCameraComponent->GetPosition().GetX()), static_cast<int>(pCameraComponent->GetPosition().GetY()),
            static_cast<int>(m_screenResolution.GetX()), static_cast<int>(m_screenResolution.GetY()) };

        if (pSpriteComponent)
        {
            SDL_Rect a = { static_cast<int>(position.GetX()), static_cast<int>(position.GetY()),
                static_cast<int>(pSpriteComponent->GetTextureRect().w), static_cast<int>(pSpriteComponent->GetTextureRect().h) };

            //Does it collide with the camera
            if (Utilities::RectangleCollisionTest(a, b))
            {
                m_renderer.Render(renderer, *pTransformComponent, *pSpriteComponent, interpolation, pCameraComponent->GetPosition(), viewPortID);
            }
        }
        else if (pAnimatedComponent)
        {
			m_renderer.Render(renderer, *pTransformComponent, *pAnimatedComponent, interpolation, pCameraComponent->GetPosition(), viewPortID);
        }
    }  
}

bool GameStateRenderSystem::HandleEvent(const Event& evt)
{
    switch (evt.GetEventType())
    {
    case Event::eEntityEvent:
        auto pEvent = evt.GetEvent<EntityEvent>();

        if (pEvent)
        {
            if (m_pBaseCameraComponent == nullptr || m_pGaulemCameraComponent == nullptr)
            {
                if (pEvent->IsEntityAdded())
                {
                    Entity& entity = pEvent->GetEntity();

                    if (entity.GetName() == "GaulemCamera")
                    {
                        m_pGaulemCameraComponent = entity.GetComponent<CameraComponent>();
                    }
                    else if (entity.GetName() == "BaseCamera")
                    {
                        m_pBaseCameraComponent = entity.GetComponent<CameraComponent>();
                    }
                }
            }
        }
        break;
    }

    return false;
}